package com.etime.shyzuul.common;

import com.etime.shyzuul.pojo.CurrentUser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 数据接口权限鉴定过滤器
 */
@Component
public class AuthcFilter extends ZuulFilter {

    @Autowired
    private RightData rightData;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 前置过滤器
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not
     * important for a filter. filterOrders do not need to be sequential.
     *
     * @return the int order of a filter
     */
    @Override
    public int filterOrder() {
        return 1;
    }

    /**
     * a "true" return from this method means that the run() method should be invoked
     *
     * @return true if the run() method should be invoked. false will not invoke the run() method
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * if shouldFilter() is true, this method will be invoked. this method is the core method of a ZuulFilter
     *
     * @return Some arbitrary artifact may be returned. Current implementation ignores it.
     * @throws ZuulException if an error occurs during execution.
     */
    @Override
    public Object run() throws ZuulException {
        boolean flag = false;
        ObjectMapper om = new ObjectMapper ();
        //获取用户访问的url地址以及token参数
        RequestContext context = RequestContext.getCurrentContext ();
        HttpServletRequest request = context.getRequest ();
        //根据token获取登录用户信息，如果是超级管理员，则直接放行
        CurrentUser user = null;
        String token = null;//request.getParameter("token");
        if (request.getHeader ("token") != null && !request.getHeader ("token").equals ("")) {
            token = request.getHeader ("token");
        }
        //swagger测试使用，后期删除
//        if (token == null) {
//            token = "6bb61e3b7bce0931da574d19d1d82c88";
//        }

        if (token != null) {
            if (stringRedisTemplate.hasKey (token)) {
                //获取用户数据
                String userstr = stringRedisTemplate.boundValueOps (token).get ();
                //刷新reids过期时间（缓存不过期）
                //stringRedisTemplate.boundValueOps (token).expire (120, TimeUnit.MINUTES);
                try {
                    user = om.readValue (userstr, CurrentUser.class);
                    if (user.getUser ().getUserid () == -1) {
                        return null;
                    }
                } catch (JsonProcessingException e) {
                    e.printStackTrace ();
                }
            }
        }
        //用户访问的url地址
        String path = request.getRequestURI ();
        //判断该资源是否需要角色授权（在权限数据中的数据接口是需要授权的接口）
        List<Integer> rolelist = rightData.getRightmap ().get (path);
        //处理rest请求的路径参数问题
        if (rolelist == null || rolelist.size () == 0) {
            String p2 = path.substring (0, path.lastIndexOf ("/"));
            rolelist = rightData.getRightmap ().get (p2);
        }
        if (rolelist != null && rolelist.size () > 0) {
            //接口的资源为null时，表示该数据接口还没有开放访问。
            if (rolelist.get (0) != null) {
                //用户已经登录，并且获取到用户信息后验证用户权限
                if (user != null) {
                    List<Integer> roleids = user.getRoleids ();
                    for (Integer needroleid : rolelist) {
                        for (Integer userrole : roleids) {
                            if (needroleid.equals (userrole)) {
                                //有权限
                                flag = true;
                                break;
                            }
                        }
                        if (flag) {
                            break;
                        }
                    }
                }
            }
        } else {
            //不需要角色授权
            flag = true;
        }
        if (!flag) {
            // 没有token，登录校验失败，拦截
            context.setSendZuulResponse (false);
            BaseMessage msg = new BaseMessage ();
            msg.setCode (-2);
            msg.setMsg ("未授权");
            try {
                String rtnmsg = om.writeValueAsString (msg);
                context.setResponseBody (rtnmsg);
            } catch (JsonProcessingException e) {
                e.printStackTrace ();
            }
            context.getResponse ().setContentType ("application/json; charset=utf-8");
        }
        return null;
    }
}
